﻿/* Copyright 2010 Igor Francé
 * 
 * This file is part of ECMADoc (http://ecmadoc.codeplex.com).
 * 
 * ECMADoc is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * ECMADoc is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with ECMADoc. 
 * If not, see http://www.gnu.org/licenses/.
 */
namespace EcmaDoc.Core
{
	using System;
	using System.Collections.Generic;
	using System.Collections.Specialized;
	using System.Diagnostics;
	using System.Reflection;
	using System.Text.RegularExpressions;

	using log4net;
	using log4net.Core;
	using log4net.Appender;
	using log4net.Layout;
	using log4net.Repository.Hierarchy;

	public static class Log
	{
		public delegate void WriteMessage(LogCategory category, string message);

		private static List<WriteMessage> writers;

		private static ILog log = LogManager.GetLogger(typeof(Log).FullName);

		internal static bool IsActive
		{
			get;
			set;
		}

		static Log()
		{
			IsActive = true;
			
			writers = new List<WriteMessage>();
			AddWriter(WriteLine);
		}

		public static void AddWriter(WriteMessage writer)
		{
			writers.Add(writer);
		}

		public static string GetLoggerName()
		{
			StackTrace stackTrace = new StackTrace();
			MethodBase thisMethod = stackTrace.GetFrame(0).GetMethod();
			MethodBase callingMethod = thisMethod;

			int offset = 0;
			StackFrame stackFrame;
			while (thisMethod.DeclaringType == callingMethod.DeclaringType)
			{
				stackFrame = stackTrace.GetFrame(++offset);
				if (stackFrame == null)
					break;

				callingMethod = stackFrame.GetMethod();
			}

			return string.Concat(callingMethod.DeclaringType.FullName, ".", callingMethod.Name);
		}

		public static void WriteLine(object message, params object[] values)
		{
			WriteLine(LogCategory.Debug, message, values);
		}

		public static void WriteLine(LogCategory category, object message, params object[] values)
		{
			if (!IsActive)
				return;
			if (message == null)
				return;

			string log = string.Format(message.ToString(), values);
			foreach (WriteMessage write in writers)
			{
				write(category, log);
			}
		}

		private static void WriteLine(LogCategory category, string message)
		{
			switch (category)
			{
				case LogCategory.Debug:
					log.Debug(message);
					break;
				case LogCategory.Info:
					log.Info(message);
					break;
				case LogCategory.Warning:
					log.Warn(message);
					break;
				case LogCategory.Error:
					log.Error(message);
					break;
				case LogCategory.Fatal:
					log.Fatal(message);
					break;
			}
		}
	}
}
